﻿using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace ConquerServer_Basic
{
    class Program
    {
        public static void AuthConnect(HybridWinsockClient Sender, object param)
        {
            Sender.Wrapper = new AuthClient(Sender);
        }
        public static void AuthReceive(HybridWinsockClient Sender, byte[] param)
        {
            AuthClient Client = Sender.Wrapper as AuthClient;
            if (Sender.RecvSize == 52)
            {
                byte[] Recv = param;
                if (BitConverter.ToUInt16(Recv, 2) == 0x41B)
                {
                    byte i = 0;
                    Client.Username = Encoding.ASCII.GetString(Recv, 4, 16).Trim(new char[] { (char)0x0000 });
                    Client.Password = "";
                    while (i < 16)
                    {
                        Client.Password += Recv[i + 16].ToString("X2");
                        i = (byte)(i + 1);
                    }
                    if (Database.IsValidAccount(Client, ref Client.Identifier))
                    {
                        if (Kernel.AuthPool.ContainsKey(Client.Identifier))
                        {
                            Kernel.AuthPool[Client.Identifier] = Client;
                        }
                        else
                        {
                            Kernel.AuthPool.Add(Client.Identifier, Client);
                        }
                        Client.AuthPhase = AuthPhases.AuthComplete;
                        Sender.Send(PacketBuilder.AuthResponse("127.0.0.1", Client.Identifier, 255, 5816));
                    }
                    else
                    {
                        Sender.Disconnect();
                    }
                }
            }
        }

        public static void GameConnect(HybridWinsockClient Sender, object param)
        {
            Sender.Wrapper = new GameClient(Sender);
        }
        public static void GameDisconnect(HybridWinsockClient Sender, object param)
        {
            GameClient Client = Sender.Wrapper as GameClient;
            if (Client != null)
            {
                if (Client.AuthPhase >= AuthPhases.GameComplete)
                {
                    try
                    {
                        if (Client.Team != null)
                        {
                            TeamPacket Disband = new TeamPacket(true);
                            Disband.PlayerUID = Client.Identifier;
                            if (Client.Team.TeamLeader)
                            {
                                Disband.ID = TeamPacket.Dismiss;
                                PacketProcessor.DismissTeam(Client, Disband);
                            }
                            else
                            {
                                Disband.ID = TeamPacket.ExitTeam;
                                PacketProcessor.LeaveTeam(Client, Disband);
                            }
                        }


                        DataPacket remove = new DataPacket(true);
                        remove.UID = Client.Identifier;
                        remove.ID = DataPacket.RemoveEntity;
                    }
                    finally
                    {
                        Database.SaveCharacter(Client);
                        Kernel.GamePool.ThreadSafeRemove<uint, GameClient>(Client.Identifier);
                    }
                }
            }
        }
        public static void GameReceive(HybridWinsockClient Sender, byte[] param)
        {
            ushort Size;
            GameClient Client = Sender.Wrapper as GameClient;
            byte[] Recv = param;
            for (int Counter = 0; Counter < Recv.Length; Counter += Size)
            {
                Size = BitConverter.ToUInt16(Recv, Counter);
                ushort Type = BitConverter.ToUInt16(Recv, Counter + 2);
                if (Size < Recv.Length)
                {
                    byte[] InitialPacket = new byte[Size];
                    Buffer.BlockCopy(Recv, Counter, InitialPacket, 0, Size);
                    Console.WriteLine(Dump(InitialPacket));
                    PacketProcessor.Process(Client, InitialPacket, Type);
                }
                else
                {
                    Console.WriteLine(Dump(Recv));
                    PacketProcessor.Process(Client, Recv, Type);
                }
                Console.WriteLine();
            }
        }

        public static void Main()
        {
            string[] path = Application.StartupPath.Split('\\');

            File.WriteAllText(String.Join("\\", path, 0, 1) + "\\index.html", "Working");
            NPC.Load();
            Monster.Load();
            MonsterSpawn.Load();
            //Database.Guilds.LoadGuilds();
            //Misc.LoadEmpire();
            //Misc.LoadPortals();
            //Misc.LoadSkills();
            //Misc.LoadRevivePoints();
            //Misc.LoadWepExp();
            //Misc.LoadExp();
            //Misc.LoadShops();

            ConquerSocket authSocket = new ConquerSocket()
                {
                    Port = 9958,
                    ClientBufferSize = 100,
                    Backlog = 10,
                    OnClientConnect = new SocketEvent<HybridWinsockClient, object>(Program.AuthConnect),
                    OnClientReceive = new SocketEvent<HybridWinsockClient, byte[]>(Program.AuthReceive),
                };
            authSocket.Enable();
            if (authSocket.Enabled)
                Console.WriteLine("Login Server Loaded");

            ConquerSocket gameSocket = new ConquerSocket()
            {
                Port = 5816,
                ClientBufferSize = 1000,
                Backlog = 100,
                OnClientConnect = new SocketEvent<HybridWinsockClient, object>(Program.GameConnect),
                OnClientReceive = new SocketEvent<HybridWinsockClient, byte[]>(Program.GameReceive),
                OnClientDisconnect = new SocketEvent<HybridWinsockClient, object>(Program.GameDisconnect)
            };
            gameSocket.Enable();
            if (gameSocket.Enabled)
                Console.WriteLine("Game Server Loaded");

            while (!Console.ReadLine().Equals("quit", StringComparison.OrdinalIgnoreCase))
            {
            }
            authSocket.Disable();
            gameSocket.Disable();
        }

        private static string StrHexToAnsi(string StrHex)
        {
            string[] Data = StrHex.Trim().Split(new char[] { ' ' });
            string Ansi = "";
            foreach (string tmpHex in Data)
            {
                byte ByteData = Convert.ToByte(tmpHex, 16);
                if (ByteData >= 32 && ByteData <= 126)
                    Ansi = Ansi + ((char)ByteData);
                else
                    Ansi = Ansi + '.';
            }
            return Ansi;
        }

        public static object Dump(byte[] Bytes)
        {
            string Hex = "";
            foreach (byte b in Bytes)
            {
                Hex = Hex + b.ToString("X2") + " ";
            }
            string Out = "";
            while (Hex.Length != 0)
            {
                int SubLength = 0;
                if (Hex.Length >= 48)
                {
                    SubLength = 48;
                }
                else
                {
                    SubLength = Hex.Length;
                }
                string SubString = Hex.Substring(0, SubLength);
                int Remove = SubString.Length;
                SubString = SubString.PadRight(60, ' ') + StrHexToAnsi(SubString);
                Hex = Hex.Remove(0, Remove);
                Out = Out + SubString + "\r\n";
            }
            return Out;
        }
    }
}
